/**
 *
 */
package org.jim.common.utils;

import cn.hutool.core.bean.BeanUtil;
import org.jim.common.ImConst;
import org.jim.common.ImPacket;
import org.jim.common.ImStatus;
import org.jim.common.http.HttpConst;
import org.jim.common.http.HttpProtocol;
import org.jim.common.packets.Command;
import org.jim.common.packets.Group;
import org.jim.common.packets.RespBody;
import org.jim.common.packets.User;
import org.jim.common.protocol.AbProtocol;
import org.jim.common.protocol.IConvertProtocolPacket;
import org.jim.common.protocol.IProtocol;
import org.jim.common.tcp.TcpProtocol;
import org.jim.common.ws.WsProtocol;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tio.core.ChannelContext;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * IM工具类;
 *
 * @author WChao
 */
public class ImKit {

    private static Logger logger = LoggerFactory.getLogger(ImKit.class);
    private static Map<String, AbProtocol> protocols = new HashMap<String, AbProtocol>();

    static {
        WsProtocol wsProtocol = new WsProtocol();
        TcpProtocol tcpProtocol = new TcpProtocol();
        HttpProtocol httpProtocol = new HttpProtocol();
        protocols.put(wsProtocol.name(), wsProtocol);
        protocols.put(tcpProtocol.name(), tcpProtocol);
        protocols.put(httpProtocol.name(), httpProtocol);
    }

    /**
     * 功能描述：[转换不同协议响应包]
     *
     * @param respBody
     * @param channelContext
     * @return
     * @author：WChao 创建时间: 2017年9月21日 下午3:21:54
     */
    public static ImPacket ConvertRespPacket(RespBody respBody, ChannelContext channelContext) {
        ImPacket respPacket = null;
        if (respBody == null) {
            return respPacket;
        }
        byte[] body;
        try {
            body = respBody.toString().getBytes(HttpConst.CHARSET_NAME);
            respPacket = ConvertRespPacket(body, respBody.getCommand(), channelContext);
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return respPacket;
    }

    /**
     * 功能描述：[转换不同协议响应包]
     *
     * @param body
     * @param channelContext
     * @return
     * @author：WChao 创建时间: 2017年9月21日 下午3:21:54
     */
    public static ImPacket ConvertRespPacket(byte[] body, Command command, ChannelContext channelContext) {
        ImPacket respPacket = null;
        IConvertProtocolPacket converter = (IConvertProtocolPacket) channelContext.getAttribute(ImConst.CONVERTER);
        if (converter != null) {
            return converter.RespPacket(body, command, channelContext);
        }
        for (Entry<String, AbProtocol> entry : protocols.entrySet()) {
            AbProtocol protocol = entry.getValue();
            IConvertProtocolPacket converterObj = protocol.getConverter();
            respPacket = converterObj.RespPacket(body, command, channelContext);
            if (respPacket != null) {
                channelContext.setAttribute(ImConst.CONVERTER, converterObj);
                return respPacket;
            }
        }
        return respPacket;
    }

    public static ImPacket ConvertRespPacket(ImPacket imPacket, Command command, ChannelContext channelContext) {
        ImPacket respPacket = ConvertRespPacket(imPacket.getBody(), command, channelContext);
        if (respPacket == null) {
            for (Entry<String, AbProtocol> entry : protocols.entrySet()) {
                AbProtocol protocol = entry.getValue();
                try {
                    boolean isProtocol = protocol.isProtocol(imPacket, channelContext);
                    if (isProtocol) {
                        IConvertProtocolPacket converterObj = protocol.getConverter();
                        respPacket = converterObj.RespPacket(imPacket.getBody(), command, channelContext);
                        if (respPacket != null) {
                            channelContext.setAttribute(ImConst.CONVERTER, converterObj);
                            return respPacket;
                        }
                    }
                } catch (Throwable e) {
                    logger.error(e.toString());
                }
            }
        }
        return respPacket;
    }

    /**
     * 获取所属终端协议;
     *
     * @param byteBuffer
     * @param channelContext
     */
    public static IProtocol protocol(ByteBuffer byteBuffer, ChannelContext channelContext) {
        for (Entry<String, AbProtocol> entry : protocols.entrySet()) {
            AbProtocol protocol = entry.getValue();
            try {
                boolean isProtocol = protocol.isProtocol(byteBuffer, channelContext);
                if (isProtocol) {
                    return protocol;
                }
            } catch (Throwable e) {
                logger.error(e.toString(), e);
            }
        }
        return null;
    }

    /**
     * 格式化状态码消息响应体;
     *
     * @param status
     * @return
     */
    public static byte[] toImStatusBody(ImStatus status) {
        return JsonKit.toJsonBytes(new RespBody().setCode(status.getCode()).setMsg(status.getDescription() + " " + status.getText()));
    }

    /**
     * 获取所有协议判断器，目前内置(HttpProtocol、WebSocketProtocol、HttpProtocol)
     *
     * @return
     */
    public static Map<String, AbProtocol> getProtocols() {
        return protocols;
    }

    /**
     * 复制用户信息不包括friends、groups下的users信息;
     *
     * @param source
     * @return
     */
    public static User copyUserWithoutFriendsGroups(User source) {
        if (source == null) {
            return null;
        }
        User user = new User();
        BeanUtil.copyProperties(source, user, "friends", "groups");
        return user;
    }

    /**
     * 复制用户信息不包括friends、groups下的users信息;
     *
     * @param source
     * @return
     */
    public static User copyUserWithoutUsers(User source) {
        if (source == null) {
            return source;
        }
        User user = new User();
        BeanUtil.copyProperties(source, user, "friends", "groups");
        List<Group> friends = source.getFriends();
        if (friends != null && !friends.isEmpty()) {
            List<Group> newFriends = new ArrayList<Group>();
            for (Group friend : friends) {
                Group newFriend = new Group();
                BeanUtil.copyProperties(friend, newFriend);
                newFriend.setUsers(null);
                newFriends.add(newFriend);
            }
            user.setFriends(newFriends);
        }
        List<Group> groups = source.getGroups();
        if (groups != null && !groups.isEmpty()) {
            List<Group> newGroups = new ArrayList<Group>();
            for (Group group : groups) {
                Group newGroup = new Group();
                BeanUtil.copyProperties(group, newGroup);
                newGroup.setUsers(null);
                newGroups.add(newGroup);
            }
            user.setGroups(newGroups);
        }
        return user;
    }

    /**
     * 复制分组或者群组，不包括users;
     *
     * @param source
     * @return
     */
    public static Group copyGroupWithoutUsers(Group source) {
        if (source == null) {
            return null;
        }
        Group group = new Group();
        BeanUtil.copyProperties(source, group, "users");
        return group;
    }
}
